home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / Car / Car.m < prev    next >
Encoding:
Text File  |  1992-06-25  |  8.1 KB  |  316 lines

  1.  
  2. /* Generated by Interface Builder */
  3.  
  4. #import <math.h>
  5. #import <appkit/nextstd.h>
  6. #import "Car_main.h"
  7. #import "Car.h"
  8. #import "Wheels.h"
  9. #import "Cycle.h"
  10. #import "DataView.h"
  11. #import "AppDelegate.h"
  12. #import "Road.h"
  13. #import "Controller.h"
  14. #import "Transmission.h"
  15. #import "GasTank.h"
  16. #import "Battery.h"
  17.  
  18. @implementation Car
  19.  
  20. - init
  21. {
  22.     [super init];
  23.     car = self;
  24.     return self;
  25. }
  26.  
  27. - read:(NXTypedStream *)stream
  28. {
  29.     [super read:stream];
  30.     NXReadTypes(stream,"fffci",&dragCoefficient,&frontalArea,&mass,&plotAcceleration,&testMode);
  31.     return self;
  32. }
  33.  
  34. - write:(NXTypedStream *)stream
  35. {
  36.     [super write:stream];
  37.     NXWriteTypes(stream,"fffci",&dragCoefficient,&frontalArea,&mass,&plotAcceleration,&testMode);
  38.     return self;
  39. }
  40.  
  41. - (float)dragCoefficient
  42. {
  43.     return dragCoefficient;
  44. }
  45.  
  46. - setDragCoefficient:(float)aNumber
  47. {
  48.     dragCoefficient = aNumber;
  49.     return self;
  50. }
  51.  
  52. - (float)frontalArea
  53. {
  54.     return frontalArea;
  55. }
  56.  
  57. - setFrontalArea:(float)aNumber
  58. {
  59.     frontalArea = aNumber;
  60.     return self;
  61. }
  62.  
  63. - (float)mass
  64. {
  65.     return mass;
  66. }
  67.  
  68. - setMass:(float)aNumber
  69. {
  70.     mass = aNumber;
  71.     return self;
  72. }
  73.  
  74. - setRoadForce:(float)aNumber
  75. {
  76.     roadForce = aNumber;
  77.     return self;
  78. }
  79.  
  80. - (float)currentVelocity
  81. {
  82.     return currentVelocity;
  83. }
  84.  
  85. - (BOOL)plotAcceleration
  86. {
  87.     return plotAcceleration;
  88. }
  89.  
  90. - setPlotAcceleration:(BOOL)flag
  91. {
  92.     plotAcceleration = flag;
  93.     return self;
  94. }
  95.  
  96. - (int)testMode;
  97. {
  98.     return testMode;
  99. }
  100.  
  101. - setTestMode:(int)mode
  102. {
  103.     testMode = mode;
  104.     return self;
  105. }
  106.  
  107. - runSimulation:sender
  108. {
  109. float Mass;
  110. float totalMass;
  111. float CdA;
  112. float rho;
  113. float Cr;
  114. float aero;
  115. float rolling;
  116. float inertial;
  117. float velocity;
  118. float acceleration;
  119. float requiredAcceleration;
  120. double theta;
  121. float gradient;
  122. float power;
  123. struct plotData point;
  124.  
  125.     [cycle reset];
  126.     [road reset];
  127.     [battery getSetForRun];
  128.     [gasTank getSetForRun];
  129.  
  130.     if ( plotAcceleration )
  131.         {
  132.         if ( !accelerationGraph )
  133.             {
  134.             accelerationGraph = [appDelegate newGraph];
  135.             [[accelerationGraph window] setTitle:"Acceleration (m/s^2)"];
  136.             }
  137.         [[accelerationGraph window] orderFront:nil];
  138.         }
  139.     [[accelerationGraph data] empty];
  140.  
  141.     if ( 1 )   // There should be another option for this graph.  Not implemented yet.
  142.         {
  143.         if ( !velocityGraph )
  144.             {
  145.             velocityGraph = [appDelegate newGraph];
  146.             [[velocityGraph window] setTitle:"Velocity (m/s)"];
  147.             }        
  148.         [[velocityGraph window] orderFront:nil];
  149.         }
  150.     [[velocityGraph data] empty];
  151.  
  152.     if ( 1 )    // There should be another option for this graph.  Not implemented yet.
  153.         {
  154.         if ( !powerGraph )
  155.             {
  156.             powerGraph = [appDelegate newGraph];
  157.             [[powerGraph window] setTitle:"Power (kW)"];
  158.             }        
  159.         [[powerGraph window] orderFront:nil];
  160.         }
  161.     [[powerGraph data] empty];
  162.  
  163.     Mass = mass;
  164.     Mass += [controller mass];
  165.     Mass += [transmission mass];
  166.     Mass += [engine mass];
  167.     Mass += [gasTank mass];
  168.     Mass += [motor mass];
  169.     Mass += [battery mass];
  170.     Mass += [wheel mass] * 4;
  171.     
  172.     CdA = dragCoefficient * frontalArea;
  173.     rho = 94 * 28.97 / 8.3143 / 293;           // air density in kg/m^3
  174.     Cr = [wheel rollingResistance];
  175.     energy = 0;
  176.  
  177. /******************************************************************************************************************************
  178.  *   That was setup.  Here's where the action really starts.                                                                  *
  179.  ******************************************************************************************************************************/
  180.     if ( testMode == ARBITRARY )
  181.         {
  182.         while ( [cycle getNextVelocity:&velocity andAcceleration:&acceleration] )  
  183.             {
  184.             totalMass = Mass + [gasTank fuelMass];
  185.             velocity = velocity / 3.6;            //conversion from km/h to m/s
  186.             acceleration = acceleration / 3.6;        //likewise
  187.             point.x = [cycle lastTime];
  188.             point.y = velocity;
  189.             [velocityGraph addData:&point];
  190.             point.y = acceleration;
  191.             [accelerationGraph addData:&point];
  192.  
  193.             aero = CdA * rho * pow(velocity+[road windSpeed],2) / 2;
  194.             rolling = totalMass * 9.807 * Cr;
  195.             inertial = totalMass * acceleration;
  196.             
  197.             theta = atan([road slope]);
  198.             gradient = 9.807 * totalMass * sin(theta);
  199.  
  200.             power = velocity * ( aero + rolling + inertial + gradient );
  201.             point.y = power / 1000;
  202.             [road advance:[cycle timeStep] atSpeed:velocity];
  203.             energy += point.y * [cycle timeStep];
  204.  
  205.             [powerGraph addData:&point];
  206.             }
  207.         }
  208.     else if ( testMode == LIMITED )
  209.         {
  210.         [cycle getNextVelocity:¤tVelocity andAcceleration:&acceleration];
  211.         currentVelocity /= 3.6;
  212.         point.x = [cycle lastTime];
  213.         point.y = currentVelocity;
  214.         [velocityGraph addData:&point];
  215.  
  216.         while ( [cycle getNextVelocity:&velocity andAcceleration:&acceleration] ) // Note: we don't use the accel returned here
  217.             {
  218.             totalMass = Mass + [gasTank fuelMass];
  219.             velocity = velocity / 3.6;            //conversion from km/h to m/s
  220.             acceleration = ( velocity - currentVelocity ) / [cycle timeStep];
  221.             requiredAcceleration = acceleration;
  222.             point.x = [cycle lastTime];
  223.  
  224.             aero = CdA * rho * pow(currentVelocity+[road windSpeed],2) / 2;
  225.             rolling = totalMass * 9.807 * Cr;
  226.             inertial = totalMass * requiredAcceleration;
  227.             
  228.             theta = atan([road slope]);
  229.             gradient = 9.807 * totalMass * sin(theta);
  230.             [road advance:[cycle timeStep] atSpeed:currentVelocity];
  231.  
  232.             if ( currentVelocity == 0 )
  233.                 power = velocity * ( aero + rolling + inertial + gradient );
  234.             else
  235.                 power = currentVelocity * ( aero + rolling + inertial + gradient );  // This is the required power in watts
  236.  
  237.             [controller powerRequired:power];        // We send a message to the controller, and the whole thing begins
  238.  
  239.             if ( (roadForce != 0) || (currentVelocity != 0) )
  240.                 inertial = roadForce - aero - rolling - gradient;  // After the messages have run their course, we get a force
  241.             else 
  242.                 inertial = 0;
  243.             acceleration = inertial / totalMass;           // a = f/m
  244.            
  245.             if ( requiredAcceleration >= 0 )                // This is so we don't use up more power than we need.
  246.                 acceleration = MIN(acceleration,requiredAcceleration);  // It's just to overcome a problem with standing starts.
  247.             else if ( requiredAcceleration < 0 )
  248.                 acceleration = MAX(acceleration,requiredAcceleration);
  249.  
  250.             point.y = currentVelocity * ( acceleration * totalMass + aero + rolling + gradient ) / 1000;
  251.             [powerGraph addData:&point];
  252.  
  253.             currentVelocity += acceleration * [cycle timeStep];     // Advance the velocity by this much
  254.             currentVelocity = MAX(currentVelocity,0);            // We never go backwards.
  255.  
  256.             point.y = currentVelocity;
  257.             [velocityGraph addData:&point];
  258.             point.y = acceleration;
  259.             [accelerationGraph addData:&point];
  260. //            fprintf(stderr,"%8f %8f %8f \n",aero,inertial,roadForce);
  261.             }
  262.         }
  263.            
  264.     [accelerationGraph drawLimits];
  265.     [velocityGraph drawLimits];
  266.     [powerGraph drawLimits];
  267.  
  268.     [[accelerationGraph window] display];
  269.     [[velocityGraph window] display];
  270.     [[powerGraph window] display];
  271.  
  272.     [appDelegate simulationEnded];
  273.  
  274.     [battery finishedRun];
  275.     [gasTank finishedRun];
  276.  
  277.     return self;
  278. }
  279.  
  280. - report:(NXStream *)stream
  281. {
  282. float Mass;
  283.  
  284.     Mass = mass;
  285.     Mass += [controller mass];
  286.     Mass += [transmission mass];
  287.     Mass += [engine mass];
  288.     Mass += [gasTank mass];
  289.     Mass += [motor mass];
  290.     Mass += [battery mass];
  291.     Mass += [wheel mass] * 4;
  292.     Mass += [gasTank fuelMass];
  293.  
  294.     NXPrintf(stream,"Car:\n");
  295.     NXPrintf(stream,"  Total Mass:%fkg\n",Mass);
  296.     NXPrintf(stream,"  Energy Used:%fkWh\n",energy/3600.0);
  297.     return self;
  298. }
  299.  
  300. @end
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314.  
  315.  
  316.